﻿Imports System.Security.Permissions
Imports DelSole.BlobService
Imports System.Collections.ObjectModel
Imports Microsoft.WindowsAzure.StorageClient
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Media
Imports System.Windows.Input

'''<summary>
'''  Interaction logic for MyControl.xaml
'''</summary>
Partial Public Class MyControl
    Inherits System.Windows.Controls.UserControl

    'Developer Account constants
    Private Const devAccount As String = "devstoreaccount1"
    Private Const devSharedKey As String = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
    Private Const devBlobEndPoint As String = "http://127.0.0.1:10000"

    Private currentAccount As String = String.Empty
    Private currentSharedKey As String = String.Empty
    Private currentBlobEndPoint As String = String.Empty

    'A collection where blobs properties are stored and bound to the UI
    'The type Object is used for compatibility with the StorageClient APIs
    Private BindingBlob As New ObservableCollection(Of CloudBlob)

    'This will be used to verify if an UriFormatException is thrown
    'when the application is started (so, do nothing) or when the user
    'passes wrong credentials
    Private IsFirstRun As Boolean = True
    Dim WithEvents AzureBlobService As BlobService
    Dim EndPoint As String


    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        ' This call is required by the Windows Form Designer.
        Try

            Dim check = BlobService.CheckIfDevelopmentStorageIsRunning()
            If check = False Then
                Dim result = MessageBox.Show("Could not start the Development Storage." & Environment.NewLine _
                             + "The local Blob storage won't be available." + Environment.NewLine _
                             + "Do you wish to continue anyway?", "", MessageBoxButton.YesNo)

                Select Case result
                    Case Is = MessageBoxResult.No
                        Application.Current.Shutdown()
                    Case Else
                        Exit Select
                End Select
            End If

            IsFirstRun = True

            If My.Computer.Network.IsAvailable = False Then
                If check = False Then
                    MessageBox.Show("Neither the developer storage nor an Internet connection available. Azure Blob Studio cannot continue.", "Azure Blob Studio", MessageBoxButton.OK, MessageBoxImage.Error)
                    Application.Current.Shutdown()
                End If

                Dim result = MessageBox.Show("No connection available. Using the local developer account.", "Azure Blob Studio", MessageBoxButton.OK, MessageBoxImage.Information)
                Me.currentAccount = My.Settings.DevAccount
                Me.currentBlobEndPoint = My.Settings.DevBlobEndPoint
                Me.currentBlobEndPoint = My.Settings.DevSharedKey
                If Me.DevAccountCheck.IsChecked = False Then
                    Me.DevAccountCheck.IsChecked = True     'This will automatically raise the Check event and enable the dev account
                End If
                PopulateControls()
            Else
                Me.currentAccount = My.Settings.MyAccount
                Me.currentSharedKey = My.Settings.MySharedKey
                Me.currentBlobEndPoint = My.Settings.MyBlobEndPoint

                'Decides what account to use based on the saved settings
                If My.Settings.WasLastAccountDeveloper = True Then
                    Me.DevAccountCheck.IsChecked = True

                    'When programmatically checking the CheckBox, the Checked event is raised
                    'and the following 2 lines of code are not necessary
                    'Me.AccountText.Text = devAccount
                    'Me.KeyText.Text = devSharedKey

                Else
                    Me.DevAccountCheck.IsChecked = False

                    'Me.AccountText.Text = Me.currentAccount
                    'Me.KeyText.Text = Me.currentSharedKey

                    'Manually raises the event
                    DevAccountCheck.RaiseEvent(New RoutedEventArgs(CheckBox.UncheckedEvent))
                End If
                PopulateControls()
            End If

            ' Add any initialization after the InitializeComponent() call.

        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    Private Sub GoButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        If Me.KeyText.Text = "" Or Me.AccountText.Text = "" Then Exit Sub

        If Me.DevAccountCheck.IsChecked = False AndAlso Me.AccountText.Text <> "devstoreaccount1" Then

            My.Settings.MyAccount = Me.AccountText.Text
            My.Settings.MySharedKey = Me.KeyText.Text
            My.Settings.MyBlobEndPoint = BlobService.CreateBlobEndPointFromAccountName(Me.AccountText.Text)
            Me.EndPoint = My.Settings.MyBlobEndPoint

            My.Settings.Save()
            Try
                If Me.AzureBlobService Is Nothing Then
                    Me.AzureBlobService = New BlobService(My.Settings.MyAccount, My.Settings.MySharedKey)
                Else
                    Me.AzureBlobService = Nothing
                    Me.AzureBlobService = New BlobService(My.Settings.MyAccount, My.Settings.MySharedKey)
                End If

                If IsFirstRun = False Then
                    PopulateControls()
                End If
            Catch ex As FormatException
                MessageBox.Show("Invalid credentials format. Please retry", "", MessageBoxButton.OK, MessageBoxImage.Error)
                Me.AccountText.Text = String.Empty
                Me.KeyText.Text = String.Empty
                Me.currentBlobEndPoint = String.Empty
                My.Settings.MyAccount = String.Empty
                My.Settings.MyBlobEndPoint = String.Empty
                My.Settings.MySharedKey = String.Empty
                My.Settings.Save()
                Exit Sub
            End Try


        Else
            If Me.AzureBlobService Is Nothing Then
                Me.AzureBlobService = New BlobService
            Else
                Me.AzureBlobService = Nothing
                Me.AzureBlobService = New BlobService
            End If

            Me.EndPoint = devBlobEndPoint
            PopulateControls()
        End If
    End Sub

    Private Sub Hyperlink_RequestNavigate(ByVal sender As System.Object, ByVal e As System.Windows.Navigation.RequestNavigateEventArgs)
        Process.Start(New ProcessStartInfo(e.Uri.AbsoluteUri))

        e.Handled = True

    End Sub

    Private Sub MenuItem_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Dim blob = CType(Me.BlobListView.SelectedItem, CloudBlob)

        Clipboard.SetText(blob.Uri.ToString)
    End Sub

    Private Sub PopulateControls()
        Me.ContainersNode.Items.Clear()

        Try
            Dim dataSource = AzureBlobService.ListContainers

            For Each container In dataSource
                Dim item As New TreeViewItem
                item.Header = container.Name
                Me.ContainersNode.Items.Add(item)
            Next

            BindingBlob.Clear()
            UriLabel.Foreground = New SolidColorBrush(Colors.White)
            UriLabel.Content = String.Empty
            IsFirstRun = False

        Catch ex As NullReferenceException
            If IsFirstRun = True Then
                IsFirstRun = False
                Exit Try
            Else
                UriLabel.Foreground = New SolidColorBrush(Colors.Orange)
                UriLabel.Content = "Please provide valid account settings and retry"
            End If

        Catch ex As UriFormatException

            If IsFirstRun = True Then
                IsFirstRun = False
                Exit Try
            Else
                UriLabel.Foreground = New SolidColorBrush(Colors.Orange)
                UriLabel.Content = "Please provide valid account settings and retry"

            End If

        Catch ex As StorageServerException
            Dim resultm = MessageBox.Show("Unable to connect to the Blob Storage. Would you like to use the dev storage instead? Choosing No, you will have to insert valid credentials", "", MessageBoxButton.YesNo, MessageBoxImage.Error)
            If resultm = MessageBoxResult.Yes Then
                Me.DevAccountCheck.IsChecked = True
                PopulateControls()
            Else
                Me.AccountText.Text = String.Empty
                Me.KeyText.Text = String.Empty
                Me.currentBlobEndPoint = String.Empty
                My.Settings.MyAccount = String.Empty
                My.Settings.MyBlobEndPoint = String.Empty
                My.Settings.MySharedKey = String.Empty
                My.Settings.Save()
            End If


        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try
    End Sub

    Private Sub MainWindow_Closing(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles Me.Unloaded
        'Saves the last account
        If DevAccountCheck.IsChecked = True Then

            My.Settings.WasLastAccountDeveloper = True
        Else

            My.Settings.WasLastAccountDeveloper = False
        End If

        My.Settings.Save()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        Dim cc As New CreateContainerWindow(Me.AzureBlobService, Me.EndPoint)
        cc.ShowDialog()
        cc = Nothing
        PopulateControls()
    End Sub

    Private Sub RemoveContainerButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles RemoveContainerButton.Click
        'Second, obtains the instance of the selected TreeViewItem
        Dim tempTreeViewItem As TreeViewItem = DirectCast(Me.ContainersTreeView.SelectedItem, TreeViewItem)

        Dim result = MessageBox.Show("Are you sure to remove " + tempTreeViewItem.Header.ToString + " container from the Blob Storage?", "", MessageBoxButton.YesNo, MessageBoxImage.Question)

        Select Case result
            Case Is = MessageBoxResult.No
                Exit Sub
            Case Is = MessageBoxResult.Yes

                Try
                    Me.AzureBlobService.DeleteContainer(tempTreeViewItem.Header.ToString)
                    PopulateControls()

                Catch ex As Exception
                    MessageBox.Show(ex.ToString)

                End Try

        End Select
    End Sub

    Private Sub ContainersTreeView_MouseLeftButtonUp(ByVal sender As Object, ByVal e As System.Windows.Input.MouseButtonEventArgs) Handles ContainersTreeView.MouseLeftButtonUp
        'First, obtains the instance of the TreeView
        Dim tempTreeview As TreeView = CType(sender, TreeView)
        'Second, obtains the instance of the selected TreeViewItem
        Dim tempTreeViewItem As TreeViewItem = CType(tempTreeview.SelectedItem, TreeViewItem)

        Me.UriLabel.Content = String.Empty
        Try
            BindingBlob = Me.AzureBlobService.ListBlobs(tempTreeViewItem.Header.ToString).ToObservableCollection
            Me.BlobListView.ItemsSource = BindingBlob

        Catch ex As Exception

        End Try

    End Sub


    Private Sub DevAccountCheck_Checked(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles DevAccountCheck.Checked


        Try
            'Switches to the dev account
            Me.KeyText.Text = devSharedKey
            Me.AccountText.Text = devAccount
            Me.EndPoint = devBlobEndPoint

            GoButton.RaiseEvent(New System.Windows.RoutedEventArgs(Button.ClickEvent))

        Catch ex As Exception

        End Try
    End Sub

    Private Sub DevAccountCheck_Unchecked(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles DevAccountCheck.Unchecked
        Try
            If My.Computer.Network.IsAvailable = False Then
                MessageBox.Show("No connection available. Forced to use the local developer storage", "Azure Blob Studio", MessageBoxButton.OK, MessageBoxImage.Warning)
                Me.DevAccountCheck.IsChecked = True
                Exit Sub
            End If


            Me.AccountText.Text = Me.currentAccount
            Me.KeyText.Text = Me.currentSharedKey
            Me.EndPoint = My.Settings.MyBlobEndPoint

            Me.ContainersNode.Items.Clear()
            BindingBlob.Clear()

            Me.UriLabel.Content = "Attempting to connect to the storage..."
            GoButton.RaiseEvent(New System.Windows.RoutedEventArgs(Button.ClickEvent))
            Me.UriLabel.Content = ""
        Catch ex As Exception

        End Try
    End Sub

    Private Sub RemoveBlobButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles RemoveBlobButton.Click

        Dim tempTreeViewItem As TreeViewItem = DirectCast(Me.ContainersTreeView.SelectedItem, TreeViewItem)

        'Retrieves selected blobs in the ListView
        Dim selectedBlobs = Me.BlobListView.SelectedItems

        If selectedBlobs.Count = 0 Then
            'No blobs selected
            Exit Sub
        End If

        Dim result = MessageBox.Show("Are you sure you want to remove the selected blobs from the Blob storage?", "", MessageBoxButton.YesNo, MessageBoxImage.Question)

        If result = MessageBoxResult.Yes Then

            Try

                With Me.ProgressBar1
                    .Maximum = selectedBlobs.Count
                    .Minimum = 0
                    .Value = 0
                End With

                Me.AzureBlobService.DeleteBlobs(selectedBlobs.Cast(Of CloudBlob))
                BindingBlob = Me.AzureBlobService.ListBlobs(tempTreeViewItem.Header.ToString).ToObservableCollection
                Me.BlobListView.ItemsSource = BindingBlob

                Me.UriLabel.Content = String.Empty
            Catch ex As Exception

                MessageBox.Show(ex.Message)

            End Try


        End If

    End Sub
    Private Sub UploadBlobButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles UploadBlobButton.Click

        Dim dialog As New Microsoft.Win32.OpenFileDialog

        With dialog
            .Title = "Select a file"
            .Filter = "All files|*.*"
            .Multiselect = True

            If .ShowDialog = True Then

                Dim tempTreeViewItem As TreeViewItem = DirectCast(Me.ContainersTreeView.SelectedItem, TreeViewItem)

                Try
                    With Me.ProgressBar1
                        .Maximum = dialog.FileNames.Count
                        .Minimum = 0
                        .Value = 0
                    End With
                    Me.AzureBlobService.UploadBlobs(tempTreeViewItem.Header.ToString, .FileNames)

                Catch ex As Exception

                    MessageBox.Show(ex.Message)
                    Exit Sub
                End Try

                Me.UriLabel.Content = String.Empty

            End If

        End With

    End Sub

    Private Sub BlobListView_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles BlobListView.KeyUp
        If e.Key = Key.Delete Then
            RemoveBlobButton.RaiseEvent(New System.Windows.RoutedEventArgs(Button.ClickEvent))
        End If
    End Sub

    Private Sub BlobListView_SelectionChanged(ByVal sender As Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Handles BlobListView.SelectionChanged
        Try
            Me.UriLabel.Content = CType(Me.BlobListView.SelectedItem, CloudBlob).Uri.ToString
        Catch ex As Exception

        End Try
    End Sub

    Private Sub AzureBlobService_DeleteBlobCompleted(ByVal sender As Object, ByVal e As DelSole.BlobService.BlobServiceEventArgs) Handles AzureBlobService.DeleteBlobCompleted
        Dispatcher.Invoke(Sub()
                              Me.UriLabel.Content = "Completed deleting " + e.BlobUri
                              Me.ProgressBar1.Value += 1
                              Me.BindingBlob.Remove(e.Blob)
                          End Sub)
    End Sub


    Private Sub AzureBlobService_UploadBlobCompleted(ByVal sender As Object, ByVal e As DelSole.BlobService.BlobServiceEventArgs) Handles AzureBlobService.UploadBlobCompleted
        Dispatcher.Invoke(Sub()
                              Me.UriLabel.Content = "Completed uploading " + e.BlobUri
                              Me.ProgressBar1.Value += 1
                              Me.BindingBlob.Add(e.Blob)
                          End Sub)

    End Sub

    Private Sub AzureBlobService_DownloadBlobCompleted(ByVal sender As Object, ByVal e As DelSole.BlobService.BlobServiceEventArgs) Handles AzureBlobService.DownloadBlobCompleted
        Dispatcher.Invoke(Sub()
                              Me.UriLabel.Content = "Completed downloading " + e.BlobUri
                              Me.ProgressBar1.Value += 1
                          End Sub)
    End Sub

    Private Sub DownloadButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles DownloadButton.Click
        Dim tempTreeViewItem As TreeViewItem = DirectCast(Me.ContainersTreeView.SelectedItem, TreeViewItem)

        'Retrieves selected blobs in the ListView
        Dim selectedBlobs = Me.BlobListView.SelectedItems

        If selectedBlobs.Count = 0 Then
            'No blobs selected
            Exit Sub
        End If

        Dim fb As New System.Windows.Forms.FolderBrowserDialog
        With fb
            .ShowNewFolderButton = True
            .Description = "Select target folder"
            .ShowDialog()
        End With

        If String.IsNullOrEmpty(fb.SelectedPath) = False Then
            Try
                With Me.ProgressBar1
                    .Maximum = selectedBlobs.Count
                    .Minimum = 0
                    .Value = 0
                End With
                Me.AzureBlobService.DownloadBlobs(CStr(tempTreeViewItem.Header), fb.SelectedPath, selectedBlobs.Cast(Of CloudBlob))

                Me.UriLabel.Content = String.Empty

                Dim result = MessageBox.Show("Download completed. Do you wish to open the target folder?", "Azure Blob Studio", MessageBoxButton.YesNo, MessageBoxImage.Question)
                If result = MessageBoxResult.No Then
                    Exit Sub
                Else
                    Process.Start(fb.SelectedPath)
                End If
            Catch ex As Exception
                MessageBox.Show(ex.Message)
                Exit Sub
            End Try

        End If
    End Sub
End Class